package com.harmony.pilot.knowledge.service;

import com.harmony.pilot.knowledge.entity.CodeSnippet;
import com.harmony.pilot.knowledge.repository.CodeSnippetRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 代码补全服务
 * 根据用户输入的关键词，提供智能代码补全建议
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CodeCompletionService {
    
    private final CodeSnippetRepository snippetRepository;
    private final EmbeddingService embeddingService;
    private final PromptBuilderService promptBuilderService;
    
    /**
     * 根据关键词搜索相关函数
     * 
     * @param keyword 用户输入的关键词（如 "napi_create_", "MyClass::"）
     * @param currentFile 当前编辑的文件路径
     * @param context 当前文件的上下文代码
     * @return 相关的代码片段列表
     */
    public List<CodeSnippet> searchByKeyword(String keyword, String currentFile, String context) {
        log.info("搜索代码补全: keyword={}, file={}", keyword, currentFile);
        
        List<CodeSnippet> results = new ArrayList<>();
        
        // 1. 精确匹配函数名
        List<CodeSnippet> exactMatches = snippetRepository.findByKeywordsContaining(keyword);
        results.addAll(exactMatches);
        
        // 2. 模糊匹配
        String fuzzyPattern = "%" + keyword + "%";
        List<CodeSnippet> fuzzyMatches = snippetRepository.findBySummaryContaining(fuzzyPattern);
        results.addAll(fuzzyMatches);
        
        // 3. 如果是类成员调用（包含::或.），查找类定义
        if (keyword.contains("::") || keyword.contains(".")) {
            String className = extractClassName(keyword);
            if (!className.isEmpty()) {
                List<CodeSnippet> classSnippets = snippetRepository.findBySnippetTypeAndKeywordsContaining("CLASS", className);
                results.addAll(classSnippets);
            }
        }
        
        // 4. 去重并排序
        results = results.stream()
            .distinct()
            .sorted(Comparator.comparingInt(s -> calculateRelevance(s, keyword, currentFile)))
            .limit(20)
            .collect(Collectors.toList());
        
        log.info("找到 {} 个相关代码片段", results.size());
        return results;
    }
    
    /**
     * 生成代码补全提示
     * 
     * @param keyword 关键词
     * @param currentFile 当前文件
     * @param context 上下文代码
     * @param maxResults 最大结果数
     * @return 补全建议
     */
    public CompletionResponse generateCompletions(String keyword, String currentFile, 
                                                  String context, int maxResults) {
        // 1. 搜索相关代码
        List<CodeSnippet> snippets = searchByKeyword(keyword, currentFile, context);
        
        // 2. 提取函数签名和示例
        List<CompletionItem> items = new ArrayList<>();
        
        for (CodeSnippet snippet : snippets.subList(0, Math.min(maxResults, snippets.size()))) {
            CompletionItem item = new CompletionItem();
            item.setLabel(snippet.getSummary());
            item.setDetail(snippet.getFilePath());
            item.setDocumentation(snippet.getContent());
            item.setKind(mapSnippetTypeToCompletionKind(snippet.getSnippetType()));
            item.setInsertText(extractInsertText(snippet));
            item.setSnippet(snippet);
            items.add(item);
        }
        
        // 3. 构建响应
        CompletionResponse response = new CompletionResponse();
        response.setItems(items);
        response.setTotalCount(snippets.size());
        response.setKeyword(keyword);
        
        return response;
    }
    
    /**
     * 生成代码续写（基于LLM）
     * 
     * @param prefix 已输入的代码前缀
     * @param context 上下文代码
     * @param currentFile 当前文件
     * @return LLM生成的续写代码
     */
    public ContinuationResponse generateContinuation(String prefix, String context, String currentFile) {
        log.info("生成代码续写: prefix={}", prefix.substring(0, Math.min(50, prefix.length())));
        
        // 1. 提取关键词
        String keyword = extractKeyword(prefix);
        
        // 2. 搜索相关代码
        List<CodeSnippet> snippets = searchByKeyword(keyword, currentFile, context);
        
        // 3. 构建LLM Prompt
        String prompt = promptBuilderService.buildContinuationPrompt(prefix, context, snippets);
        
        // 4. 调用LLM生成续写
        // TODO: 调用LLM服务
        
        ContinuationResponse response = new ContinuationResponse();
        response.setPrefix(prefix);
        response.setContextSnippets(snippets.size());
        response.setPrompt(prompt);
        
        return response;
    }
    
    /**
     * 根据函数名查找使用示例
     * 
     * @param functionName 函数名
     * @return 使用示例列表
     */
    public List<CodeSnippet> findUsageExamples(String functionName) {
        log.info("查找函数使用示例: {}", functionName);
        
        List<CodeSnippet> examples = new ArrayList<>();
        
        // 1. 查找函数定义
        List<CodeSnippet> definitions = snippetRepository.findBySnippetTypeAndKeywordsContaining("FUNCTION", functionName);
        examples.addAll(definitions);
        
        // 2. 查找测试用例中的使用
        List<CodeSnippet> testCases = snippetRepository.findByIsTestTrueAndContentContaining(functionName);
        examples.addAll(testCases);
        
        // 3. 查找其他文件中的调用
        List<CodeSnippet> usages = snippetRepository.findByContentContaining(functionName);
        examples.addAll(usages.stream()
            .filter(s -> !s.getSnippetType().equals("FUNCTION"))
            .limit(10)
            .collect(Collectors.toList()));
        
        return examples.stream()
            .distinct()
            .limit(20)
            .collect(Collectors.toList());
    }
    
    /**
     * 智能函数参数提示
     * 
     * @param functionName 函数名
     * @param currentParams 已输入的参数
     * @return 参数提示
     */
    public ParameterHintResponse getParameterHints(String functionName, List<String> currentParams) {
        log.info("获取参数提示: function={}, paramCount={}", functionName, currentParams.size());
        
        // 查找函数定义
        List<CodeSnippet> functions = snippetRepository.findBySnippetTypeAndKeywordsContaining("FUNCTION", functionName);
        
        ParameterHintResponse response = new ParameterHintResponse();
        response.setFunctionName(functionName);
        response.setCurrentParamIndex(currentParams.size());
        
        if (!functions.isEmpty()) {
            CodeSnippet function = functions.get(0);
            // 解析参数信息
            List<ParameterInfo> params = parseParameters(function.getMetadata());
            response.setParameters(params);
            
            if (currentParams.size() < params.size()) {
                ParameterInfo nextParam = params.get(currentParams.size());
                response.setCurrentParameter(nextParam);
            }
        }
        
        return response;
    }
    
    /**
     * 计算相关度
     */
    private int calculateRelevance(CodeSnippet snippet, String keyword, String currentFile) {
        int score = 0;
        
        // 完全匹配加分
        if (snippet.getSummary() != null && snippet.getSummary().contains(keyword)) {
            score += 100;
        }
        
        // 同模块加分
        if (currentFile != null && snippet.getModuleName() != null) {
            if (currentFile.contains(snippet.getModuleName())) {
                score += 50;
            }
        }
        
        // 函数类型优先
        if ("FUNCTION".equals(snippet.getSnippetType())) {
            score += 30;
        }
        
        // 测试示例次优先
        if ("TEST_CASE".equals(snippet.getSnippetType())) {
            score += 20;
        }
        
        return -score; // 负数用于降序排序
    }
    
    /**
     * 提取类名
     */
    private String extractClassName(String keyword) {
        if (keyword.contains("::")) {
            return keyword.substring(0, keyword.indexOf("::"));
        } else if (keyword.contains(".")) {
            return keyword.substring(0, keyword.indexOf("."));
        }
        return "";
    }
    
    /**
     * 提取关键词
     */
    private String extractKeyword(String prefix) {
        // 简单实现：提取最后一个单词
        String[] words = prefix.trim().split("[\\s\\(\\)\\{\\}\\[\\];,]");
        if (words.length > 0) {
            return words[words.length - 1];
        }
        return prefix;
    }
    
    /**
     * 提取插入文本
     */
    private String extractInsertText(CodeSnippet snippet) {
        if ("FUNCTION".equals(snippet.getSnippetType())) {
            // 从summary中提取函数签名
            String summary = snippet.getSummary();
            if (summary != null && summary.contains("(")) {
                return summary.substring(summary.lastIndexOf(" ") + 1);
            }
        }
        return snippet.getSummary();
    }
    
    /**
     * 映射片段类型到补全类型
     */
    private String mapSnippetTypeToCompletionKind(String snippetType) {
        switch (snippetType) {
            case "FUNCTION": return "Function";
            case "CLASS": return "Class";
            case "FIELD": return "Field";
            case "METHOD": return "Method";
            default: return "Text";
        }
    }
    
    /**
     * 解析参数信息
     */
    private List<ParameterInfo> parseParameters(String metadata) {
        // TODO: 从JSON metadata中解析参数
        return new ArrayList<>();
    }
    
    // DTO类
    public static class CompletionResponse {
        private List<CompletionItem> items;
        private int totalCount;
        private String keyword;
        
        // getters and setters
        public List<CompletionItem> getItems() { return items; }
        public void setItems(List<CompletionItem> items) { this.items = items; }
        public int getTotalCount() { return totalCount; }
        public void setTotalCount(int totalCount) { this.totalCount = totalCount; }
        public String getKeyword() { return keyword; }
        public void setKeyword(String keyword) { this.keyword = keyword; }
    }
    
    public static class CompletionItem {
        private String label;
        private String detail;
        private String documentation;
        private String kind;
        private String insertText;
        private CodeSnippet snippet;
        
        // getters and setters
        public String getLabel() { return label; }
        public void setLabel(String label) { this.label = label; }
        public String getDetail() { return detail; }
        public void setDetail(String detail) { this.detail = detail; }
        public String getDocumentation() { return documentation; }
        public void setDocumentation(String documentation) { this.documentation = documentation; }
        public String getKind() { return kind; }
        public void setKind(String kind) { this.kind = kind; }
        public String getInsertText() { return insertText; }
        public void setInsertText(String insertText) { this.insertText = insertText; }
        public CodeSnippet getSnippet() { return snippet; }
        public void setSnippet(CodeSnippet snippet) { this.snippet = snippet; }
    }
    
    public static class ContinuationResponse {
        private String prefix;
        private String continuation;
        private int contextSnippets;
        private String prompt;
        
        // getters and setters
        public String getPrefix() { return prefix; }
        public void setPrefix(String prefix) { this.prefix = prefix; }
        public String getContinuation() { return continuation; }
        public void setContinuation(String continuation) { this.continuation = continuation; }
        public int getContextSnippets() { return contextSnippets; }
        public void setContextSnippets(int contextSnippets) { this.contextSnippets = contextSnippets; }
        public String getPrompt() { return prompt; }
        public void setPrompt(String prompt) { this.prompt = prompt; }
    }
    
    public static class ParameterHintResponse {
        private String functionName;
        private int currentParamIndex;
        private List<ParameterInfo> parameters;
        private ParameterInfo currentParameter;
        
        // getters and setters
        public String getFunctionName() { return functionName; }
        public void setFunctionName(String functionName) { this.functionName = functionName; }
        public int getCurrentParamIndex() { return currentParamIndex; }
        public void setCurrentParamIndex(int currentParamIndex) { this.currentParamIndex = currentParamIndex; }
        public List<ParameterInfo> getParameters() { return parameters; }
        public void setParameters(List<ParameterInfo> parameters) { this.parameters = parameters; }
        public ParameterInfo getCurrentParameter() { return currentParameter; }
        public void setCurrentParameter(ParameterInfo currentParameter) { this.currentParameter = currentParameter; }
    }
    
    public static class ParameterInfo {
        private String name;
        private String type;
        private String description;
        private boolean optional;
        
        // getters and setters
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        public boolean isOptional() { return optional; }
        public void setOptional(boolean optional) { this.optional = optional; }
    }
}

